from wxPython._core import wxHSCROLL, wxVSCROLL, wxID_OK
from gtk.keysyms import diaeresis
from wx.lib.mvctree import Transform
import wx
import math
import matrix
import convert
import time
from PIL import Image

N = 16
ID_OPEN = 1
ID_EXIT = 2
ID_SAVE = 3
ID_CONFIRM = 4
ID_CHK_EXTEND = 5

ID_MIRROR_VERTICAL = 10
ID_MIRROR_HORIZONTAL = 11
ID_CHK_ROTATE = 12
ID_CHK_TRANSLATE = 13
ID_CHK_SHEAR = 14
ID_CHK_SHEAR = 15
ID_CHK_SCALE = 16

ID_TEST = 999
ID_TEST2 = 9999


    
class mainLayout(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,parent,id,title,size = (1280,720),style = wx.DEFAULT_FRAME_STYLE)
        
        self.vboxMain_staticbox = wx.StaticBox(self, -1, "")
        
        self.toolBar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER)
        self.toolBar_VERTICAL = wx.ToolBar(self,-1,style = wx.VERTICAL)
        self.scrollW = wx.ScrolledWindow(self,-1,style = wxHSCROLL | wxVSCROLL)
        self.tcTranslate_X = wx.TextCtrl(self.toolBar, -1, "")
        self.tcTranslate_Y = wx.TextCtrl(self.toolBar, -1, "")
        self.tcAngle = wx.TextCtrl(self.toolBar,-1, "")
        self.tcShearX = wx.TextCtrl(self.toolBar,-1,"")
        self.tcShearY = wx.TextCtrl(self.toolBar,-1,"")
        self.tcScaleX = wx.TextCtrl(self.toolBar,-1,"")
        self.tcScaleY = wx.TextCtrl(self.toolBar,-1,"")
        self.lblScale_X = wx.StaticText(self.toolBar,-1,"Scale X: ")
        self.lblScale_Y = wx.StaticText(self.toolBar,-1,"Scale Y: ")
        self.lblAngle = wx.StaticText(self.toolBar,-1,"Angle: ")
        self.lblTranslate_X = wx.StaticText(self.toolBar, -1, "X:")
        self.lblTranslate_Y = wx.StaticText(self.toolBar, -1, "Y:")
        self.lblShearH = wx.StaticText(self.toolBar,-1, "H: ")
        self.lblShearV = wx.StaticText(self.toolBar,-1, "V: ")
        self.chkExtend = wx.CheckBox(self.toolBar,-1,'Extend Canvas Mode')
        
        #self.btnConfirm = wx.Button(self.toolBar,ID_CONFIRM,"Confirm",wx.DefaultPosition,wx.DefaultSize)
        
        imgFile = "icon/confirm.png"
        imgButton = wx.Image(imgFile,wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.btnImage = wx.BitmapButton(self.toolBar,ID_CONFIRM,imgButton,wx.DefaultPosition,wx.DefaultSize)
        
        self.boolCheck = False
        self.prePix = None
        #self.toolBar_Trarm = self.CreateToolBERTICAL)
        self.__properties()        
        self.__layout()
        
        self.SetIcon(wx.Icon('icon/icon.ico',wx.BITMAP_TYPE_ICO))
        self.MinSize = (800,600)
        self.CenterOnScreen()
        self.Show(True)
    def __properties(self):
        self.toolBar.SetToolBitmapSize((40,40))
        self.toolBar_VERTICAL.SetToolBitmapSize((30,30))
        self.tcTranslate_X.SetValue('0')
        self.tcTranslate_X.Disable()
        self.tcTranslate_Y.SetValue('0')
        self.tcTranslate_Y.Disable()
        self.tcAngle.SetValue('0')
        self.tcAngle.Disable()
        self.tcShearX.SetValue('0')
        self.tcShearX.Disable()
        self.tcShearY.SetValue('0')
        self.tcShearY.Disable()
        self.tcScaleX.SetValue('100')
        self.tcScaleX.Disable()
        self.tcScaleY.SetValue('100')
        self.tcScaleY.Disable()
    
        
        #pass
    
    def __layout(self):
        
        vboxMain = wx.StaticBoxSizer(self.vboxMain_staticbox, wx.VERTICAL)
                   
        self.toolBar.AddLabelTool(ID_OPEN,'',wx.Bitmap('icon/open.png'),shortHelp='Open')
        self.toolBar.AddLabelTool(ID_SAVE,'',wx.Bitmap('icon/save.png'),shortHelp='Save')
        self.toolBar.AddLabelTool(ID_EXIT,'',wx.Bitmap('icon/exit.png'),shortHelp='Exit')
        self.toolBar.AddSeparator()
        self.toolBar.AddControl(self.lblTranslate_X)
        self.toolBar.AddControl(self.tcTranslate_X)
        self.toolBar.AddControl(self.lblTranslate_Y)
        self.toolBar.AddControl(self.tcTranslate_Y)
        self.toolBar.AddControl(self.lblAngle)
        self.toolBar.AddControl(self.tcAngle)
        self.toolBar.AddControl(self.lblShearH)
        self.toolBar.AddControl(self.tcShearX)
        self.toolBar.AddControl(self.lblShearV)
        self.toolBar.AddControl(self.tcShearY)
        self.toolBar.AddControl(self.lblScale_X)
        self.toolBar.AddControl(self.tcScaleX)
        self.toolBar.AddControl(self.lblScale_Y)
        self.toolBar.AddControl(self.tcScaleY)
        self.toolBar.AddSeparator()
        self.toolBar.AddControl(self.chkExtend)
        #self.toolBar.AddControl(self.btnConfirm)
        self.toolBar.AddControl(self.btnImage)
        self.toolBar.Realize()
        
        #vboxMain.Add(self.toolBar,0,wx.EXPAND)
        
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        
        self.toolBar_VERTICAL.AddLabelTool(ID_MIRROR_VERTICAL,'',wx.Bitmap('icon/flipV.png'),shortHelp='Flip Vertical')
        self.toolBar_VERTICAL.AddLabelTool(ID_MIRROR_HORIZONTAL,'',wx.Bitmap('icon/flipH.png'),shortHelp='Flip Horizontal')
        self.toolBar_VERTICAL.AddCheckTool(ID_CHK_SCALE,wx.Bitmap('icon/scale.png'),shortHelp='Scale')
        self.toolBar_VERTICAL.AddCheckTool(ID_CHK_SHEAR,wx.Bitmap('icon/shear.png'),shortHelp='Shear')
        self.toolBar_VERTICAL.AddCheckTool(ID_CHK_ROTATE,wx.Bitmap('icon/flip.png'),shortHelp='Rotate')
        self.toolBar_VERTICAL.AddCheckTool(ID_CHK_TRANSLATE,wx.Bitmap('icon/translate.png'),shortHelp='Translate')
        
                
        self.toolBar_VERTICAL.Realize()
        
        self.hbox.Add(self.toolBar_VERTICAL,0,wx.TOP ,150)
 
        self.hbox.Add(self.scrollW,1,wx.EXPAND)
        
        vboxMain.Add(self.hbox,1,wx.EXPAND)
        
        self.Bind(wx.EVT_TOOL, self.OnOpen, id = ID_OPEN)
        self.Bind(wx.EVT_TOOL, self.OnSave, id = ID_SAVE)
        self.Bind(wx.EVT_TOOL, self.OnExit, id = ID_EXIT)
        self.Bind(wx.EVT_TOOL, self.SetMode, id = ID_CHK_SHEAR)
        self.Bind(wx.EVT_TOOL, self.SetMode, id = ID_CHK_ROTATE)
        self.Bind(wx.EVT_TOOL, self.SetMode, id = ID_CHK_TRANSLATE)
        self.Bind(wx.EVT_TOOL, self.SetMode, id = ID_CHK_SCALE)
        self.Bind(wx.EVT_TOOL, self.OnMirrorVertical, id = ID_MIRROR_VERTICAL)
        self.Bind(wx.EVT_TOOL, self.OnMirrorHorizontal, id = ID_MIRROR_HORIZONTAL)
        #wx.EVT_CHECKBOX(self.toolBar,self.chkExtend.GetId(), self.OnCheckExtendCanvas)
        self.Bind(wx.EVT_BUTTON, self.OnConfirm, id = ID_CONFIRM)
              
        self.SetSizer(vboxMain)
        self.Layout()
        
    def OnCheckExtendCanvas(self,event):
        if self.chkExtend.GetValue():
            self.boolCheck = True
        else:
            self.boolCheck = False
        

    def OnSave(self,event):
        dialog = wx.FileDialog(None,style = wx.SAVE | wx.OVERWRITE_PROMPT)
        if dialog.ShowModal() == wxID_OK:
            self.new.save(dialog.GetPath())
        dialog.Destroy()
          
    def SetMode(self,event):
        for id in [ID_CHK_ROTATE,ID_CHK_TRANSLATE,ID_CHK_SHEAR,ID_CHK_SCALE]:
            self.toolBar_VERTICAL.ToggleTool(id,0)
        self.toolBar_VERTICAL.ToggleTool(event.GetId(),1)
        
        if event.GetId() == ID_CHK_ROTATE:
            self.tcTranslate_X.Disable()
            self.tcTranslate_Y.Disable()
            self.tcShearX.Disable()
            self.tcShearY.Disable()
            self.tcScaleX.Disable()
            self.tcScaleY.Disable()
            if self.tcAngle.IsEnabled():
                self.tcAngle.Disable()
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),0)
            else:
                self.tcAngle.Enable(True)
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),1)
        elif event.GetId() == ID_CHK_TRANSLATE:
            self.tcAngle.Disable()
            self.tcShearX.Disable()
            self.tcShearY.Disable()
            self.tcScaleX.Disable()
            self.tcScaleY.Disable()
            if self.tcTranslate_X.IsEnabled() and self.tcTranslate_Y.IsEnabled():
                self.tcTranslate_X.Disable()
                self.tcTranslate_Y.Disable()
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),0)
            else:
                self.tcTranslate_X.Enable(True)
                self.tcTranslate_Y.Enable(True)
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),1)
        elif event.GetId() == ID_CHK_SHEAR:
            self.tcAngle.Disable()
            self.tcTranslate_X.Disable()
            self.tcTranslate_Y.Disable()
            self.tcScaleX.Disable()
            self.tcScaleY.Disable()
            if self.tcShearX.IsEnabled() and self.tcShearY.IsEnabled():
                self.tcShearX.Disable()
                self.tcShearY.Disable()
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),0)
            else:
                self.tcShearX.Enable(True)
                self.tcShearY.Enable(True)
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),1)
        elif event.GetId() == ID_CHK_SCALE:
            self.tcAngle.Disable()
            self.tcShearX.Disable()
            self.tcShearY.Disable()
            self.tcTranslate_X.Disable()
            self.tcTranslate_Y.Disable()
            if self.tcScaleX.IsEnabled() and self.tcScaleY.IsEnabled():
                self.tcScaleX.Disable()
                self.tcScaleY.Disable()
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),0)
            else:
                self.tcScaleX.Enable(True)
                self.tcScaleY.Enable(True)
                self.toolBar_VERTICAL.ToggleTool(event.GetId(),1)
    
    def OnMirrorHorizontal(self,event):
        self.new = Image.new("RGBA",(self.srcImage.size[0],self.srcImage.size[1]))
        oldPix = self.srcImage.load()
        newPix = self.new.load()
        for x in range(self.srcImage.size[0]):
            for y in range(self.srcImage.size[1]):                
                newPix[self.srcImage.size[0] - x -1,y] =  oldPix[x,y]
        self.srcImage = self.new
        src = convert.Convert.pilToBitmap(self.new)
        self.prePix.Destroy()
        self.prePix = wx.StaticBitmap(self.scrollW,01,src)
        self.scrollW.SetScrollbars(20,20,src.GetWidth()/20,src.GetHeight()/20)
        self.refreshSize()
    
    def OnMirrorVertical(self,event):
        self.new = Image.new("RGBA",(self.srcImage.size[0],self.srcImage.size[1]))
        oldPix = self.srcImage.load()
        newPix = self.new.load()
        for x in range(self.srcImage.size[0]):
            for y in range(self.srcImage.size[1]):                
                newPix[x,self.srcImage.size[1]-y-1] =  oldPix[x,y]
        self.srcImage = self.new
        src = convert.Convert.pilToBitmap(self.new)
        self.prePix.Destroy()
        self.prePix = wx.StaticBitmap(self.scrollW,01,src)
        self.scrollW.SetScrollbars(20,20,src.GetWidth()/20,src.GetHeight()/20)
        self.refreshSize()
        
    def refreshSize(self):
        self.Size = (self.Size[0]+1,self.Size[1]+1)
        self.Size = (self.Size[0]-1,self.Size[1]-1)
        
    def Translate(self,point,dHorizontal,dVertical):

        x_moi = point[0]+dHorizontal
        y_moi = point[1]+dVertical
        return (x_moi,y_moi)
        
    def OnTest(self,event):
        '''
        link = Imageof.        old_pic = link.load()
        
        new = Image.new("RGBA",(link.size[0]+50,link.size[1]+50))
        new_pic = new.load()
        
        afteanslate_X, afterTranslate_Y = self.Translate((0,0), 50)
        if 0 <= afterTranslate_X and afterTranslate_X <= new.size[0] and 0 <= afterTranslate_Y and afterTranslate_Y <= new.size[1]:
            new_pic[50,50] = old_pic[afterTranslate_X,afterTranslate_Y]
        print old_pic[0,0]
        print new_pic[0,0]
        '''
        print self.tcAngle.GetValue()
        # print width, height
        #print link.size[0],link.size[1]
        # Thong in ve RGB tai 0,0
        #print old_pic[0,0]
        # print new width, new height
        #print new.size[0],new.size[1]
    
    def ExtendCanvas(self,matrixA):
        '''
        1) Nhan 4 dinh voi ma tran Transform
        2) Tim max,min cua 4 dinh moi
        3) Size := max - min + 1
        4) Translate(-minx , -miny) * ma tran Transform
        '''
        if self.chkExtend.GetValue() == True:
            arrayVertex = [(0,0),
                           (self.srcImage.size[0]-1,0),
                           (self.srcImage.size[0]-1,self.srcImage.size[1]-1),
                           (0,self.srcImage.size[1]-1)
                           ]
            arrayVertex_New = []
            for i in arrayVertex:
                matrixEachVertex = matrix.Matrix.PointToMatrix(i)
                matrixNewVertex = matrix.Matrix.MultiplyMatrix(matrixA, matrixEachVertex)
                arrayVertex_New.append(matrix.Matrix.MatrixToPoint(matrixNewVertex))
                
            min_x = arrayVertex_New[0][0]
            min_y = arrayVertex_New[0][1]
            
            max_x = arrayVertex_New[0][0]
            max_y = arrayVertex_New[0][1]
            
            for aVertex in arrayVertex_New:
                if(aVertex[0] < min_x ):
                    min_x = aVertex[0]
                if(aVertex[1] < min_y):
                    min_y = aVertex[1]
                if(aVertex[0] > max_x ):
                    max_x = aVertex[0]
                if(aVertex[1] > max_y):
                    max_y = aVertex[1]
            if min_x < 0 or min_y < 0:
                if min_x < 0:
                    min_x = -min_x
                else:
                    min_X = 0
                if min_y < 0:
                    min_y = -min_y
                else:
                    min_y = 0            
            new_width = (int)(max_x + min_x + 1)
            new_height = (int)(max_y + min_y + 1)

            matrixB = matrix.Matrix.MultiplyMatrix(matrix.Matrix.getTranslateMatrix(min_x, min_y),matrixA)                                                       
            self.Transform(matrixB,new_width,new_height)
        else: 
            self.Transform(matrixA, self.srcImage.size[0], self.srcImage.size[1])       
  
    
    def Transform(self,matrixA,width,height):
        self.new = Image.new("RGBA",(width,height))
        newPix = self.new.load()
        #wx.MessageBox(str(len(self.srcImage.load()[0,0])))
        start = time.time()
        invMatrix = matrix.Matrix.InverseMatrix(matrixA)
        destPixel = [0,0,0,0]
        for x in range(width):
            for y in range(height):
                #try:
                # CODE HERE
                oldX, oldY = matrix.Matrix.MatrixToPoint(matrix.Matrix.MultiplyMatrix31(invMatrix, matrix.Matrix.PointToMatrix((x,y))))

                if oldX < 0 or oldY < 0 or oldX > self.srcImage.size[0] or oldY > self.srcImage.size[1]:
                    newPix[x,y] = (0,0,0,0)
                    continue
                    
                # CODE HERE

                #The hard way with area weighting
                
                deltaX = (oldX-int(oldX))*16
                deltaY = (oldY-int(oldY))*16
                              
                PixelS00 = convert.Convert.getPixel(oldX,oldY,self.srcImage)
                PixelS01 = convert.Convert.getPixel(oldX,oldY+1,self.srcImage)
                PixelS10 = convert.Convert.getPixel(oldX+1,oldY,self.srcImage)
                PixelS11 = convert.Convert.getPixel(oldX+1,oldY+1,self.srcImage)
                
                
                
                destPixel[0] = ((16 - deltaX) * (16 - deltaY) * PixelS00[0] +
                                      deltaX * (16 - deltaY) * PixelS10[0]  +
                                      (16 - deltaX) * deltaY * PixelS01[0]  +
                                      deltaX * deltaY * PixelS11[0]) / 256
                destPixel[1] = ((16 - deltaX) * (16 - deltaY) * PixelS00[1] +
                                      deltaX * (16 - deltaY) * PixelS10[1]  +
                                      (16 - deltaX) * deltaY * PixelS01[1]  +
                                      deltaX * deltaY * PixelS11[1]) / 256
                destPixel[2] = ((16 - deltaX) * (16 - deltaY) * PixelS00[2] +
                                      deltaX * (16 - deltaY) * PixelS10[2]  +
                                      (16 - deltaX) * deltaY * PixelS01[2]  +
                                      deltaX * deltaY * PixelS11[2]) / 256
                if self.srcImage.mode == "RGBA":
                    destPixel[3] = ((16 - deltaX) * (16 - deltaY) * PixelS00[3] +
                                          deltaX * (16 - deltaY) * PixelS10[3]  +
                                          (16 - deltaX) * deltaY * PixelS01[3]  +
                                          deltaX * deltaY * PixelS11[3]) / 256
                else:
                    destPixel[3] = 255                                                                                                                
                newPix[x,y] = ( destPixel[0], destPixel[1], destPixel[2],destPixel[3])
                '''
                a = convert.Convert.getPixel(oldX, oldY, self.srcImage)
                if (a != None):
                    newPix[x,y] = a 
                '''               
#                except Exception,a:
#                   print x,y,a,oldX,oldY
        self.srcImage = self.new
        src = convert.Convert.pilToBitmap(self.new)
        self.prePix.Destroy()
        self.prePix = wx.StaticBitmap(self.scrollW,01,src)
        
        self.scrollW.SetScrollbars(20,20,src.GetWidth()/20,src.GetHeight()/20)
        self.refreshSize()  
        wx.MessageBox(str(time.time() - start))
                    
    def OnConfirm(self,event):
        if  self.tcTranslate_X.IsEnabled() and self.tcTranslate_Y.IsEnabled():
            matrixA = matrix.Matrix.getTranslateMatrix((int)(self.tcTranslate_X.GetValue()), (int)(self.tcTranslate_Y.GetValue()))
            self.ExtendCanvas(matrixA)
            
        elif self.tcAngle.IsEnabled():
            matrixA = matrix.Matrix.getRotateMatrix((float)(self.tcAngle.GetValue()))
            self.ExtendCanvas(matrixA)
           
        elif self.tcShearX.IsEnabled() and self.tcShearY.IsEnabled():
            matrixA = matrix.Matrix.getShearMatrix((float)(self.tcShearX.GetValue())/100.,(float)(self.tcShearY.GetValue())/100.)
            self.ExtendCanvas(matrixA)
        elif self.tcScaleX.IsEnabled() and self.tcScaleY.IsEnabled():
            if (float)(self.tcScaleX.GetValue()) <= 0:
                scaleX = 1
            else:
                scaleX = (float)(self.tcScaleX.GetValue())/100. 
            if (float)(self.tcScaleY.GetValue()) <= 0:
                scaleY = 1
            else:
                scaleY = (float)(self.tcScaleY.GetValue())/100.
            matrixA = matrix.Matrix.getScaleMatrix(scaleX,scaleY)
            self.ExtendCanvas(matrixA)
        else: 
            wx.MessageBox('none')
                
    def OnRotate(self,event):
        if self.tcAngle.GetValue() != '0':
            link = Image.open(self.link)
            afterRotate = link.rotate((float)(self.tcAngle.GetValue()))
            src = convert.Convert.pilToBitmap(afterRotate)
            wx.StaticBitmap(self.scrollW,-1,src)
            self.scrollW.SetScrollbars(20,20,src.GetWidth()/20,src.GetHeight()/20)
            self.refreshSize()
      
        
    def OnExit(self,event):
        self.Close()
        
    def OnOpen(self,event):
        dialog = wx.FileDialog(None,style = wx.OPEN)
        if dialog.ShowModal() == wxID_OK:
            link = dialog.GetPath()
            # bien anh toan cuc
            self.srcImage = Image.open(link)
            src = wx.Image(link,wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            if self.prePix != None:
                self.prePix.Destroy()
            self.prePix = wx.StaticBitmap(self.scrollW,-1,src)
            self.scrollW.SetScrollbars(20,20,src.GetWidth()/20,src.GetHeight()/20)    
        dialog.Destroy()
        

    
app = wx.App()
mainLayout(None,-1,"Linear Transformation Demonstration")
app.MainLoop()        